//给你二叉树的根结点 root ，请你将它展开为一个单链表： 
//
// 
// 展开后的单链表应该同样使用 TreeNode ，其中 right 子指针指向链表中下一个结点，而左子指针始终为 null 。 
// 展开后的单链表应该与二叉树 先序遍历 顺序相同。 
// 
//
// 
//
// 示例 1： 
//
// 
//输入：root = [1,2,5,3,4,null,6]
//输出：[1,null,2,null,3,null,4,null,5,null,6]
// 
//
// 示例 2： 
//
// 
//输入：root = []
//输出：[]
// 
//
// 示例 3： 
//
// 
//输入：root = [0]
//输出：[0]
// 
//
// 
//
// 提示： 
//
// 
// 树中结点数在范围 [0, 2000] 内 
// -100 <= Node.val <= 100 
// 
//
// 
//
// 进阶：你可以使用原地算法（O(1) 额外空间）展开这棵树吗？ 
// Related Topics 栈 树 深度优先搜索 链表 二叉树 👍 1079 👎 0

package leetcode.editor.cn;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class _114_FlattenBinaryTreeToLinkedList {
    private static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        private TreeNode() {
        }

        private TreeNode(int val) {
            this.val = val;
        }

        private TreeNode(int val, TreeNode left, TreeNode right) {
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }

    public static void main(String[] args) {
        Solution solution = new _114_FlattenBinaryTreeToLinkedList().new Solution();
        TreeNode root = new TreeNode(1,
                new TreeNode(2, new TreeNode(3), new TreeNode(4)),
                new TreeNode(5, null, new TreeNode(6)));

        solution.flatten(root);
        preTraversal(root);
//        preTraversal(root);
//        System.out.println();
//        while (root != null) {
//            if (root.left != null) System.out.println("left is not null!");
//            System.out.print(root.val + " ");
//            root = root.right;
//        }

    }

    private static void preTraversal(TreeNode root) {
        if (root == null) {
            System.out.print("null ");
            return;
        }
        System.out.print(root.val + " ");
        preTraversal(root.left);
        preTraversal(root.right);
    }

    class Solution {
        public void flatten(TreeNode root) {
            TreeNode cur = root;
            while (cur != null) {
                if (cur.left != null) {
                    TreeNode next = cur.left;
                    TreeNode pre = next;
                    while (pre.right != null) {
                        pre = pre.right;
                    }
                    pre.right = cur.right;
                    cur.left = null;
                    cur.right = next;
                }
                cur = cur.right;
            }
        }

        public void flatten2(TreeNode root) {
            TreeNode curr = root;
            while (curr != null) {
                if (curr.left != null) {
                    TreeNode next = curr.left;
                    TreeNode predecessor = next;
                    while (predecessor.right != null) {
                        predecessor = predecessor.right;
                    }
                    predecessor.right = curr.right;
                    curr.left = null;
                    curr.right = next;
                }
                curr = curr.right;
            }
        }
    }

    class Solution3 {
        public void flatten(TreeNode root) {
            List<TreeNode> list = new ArrayList<>();
            preTraversal(root, list);

            for (int i = 1; i < list.size(); i++) {
                TreeNode pre = list.get(i - 1);
                TreeNode cur = list.get(i);
                pre.left = null;
                pre.right = cur;
            }

            System.out.println();
        }

        private void preTraversal(TreeNode root, List<TreeNode> list) {
            if (root == null) return;
            list.add(root);
            preTraversal(root.left, list);
            preTraversal(root.right, list);
        }
    }

    //leetcode submit region begin(Prohibit modification and deletion)

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     * int val;
     * TreeNode left;
     * TreeNode right;
     * TreeNode() {}
     * TreeNode(int val) { this.val = val; }
     * TreeNode(int val, TreeNode left, TreeNode right) {
     * this.val = val;
     * this.left = left;
     * this.right = right;
     * }
     * }
     */
    class Solution2 {
        public void flatten(TreeNode root) {
            if (root == null || (root.left == null && root.right == null)) return;
            Stack<TreeNode> st = new Stack<>();
            TreeNode cur = null;
            st.push(root);
            while (!st.isEmpty()) {
                TreeNode pop = st.pop();
                if (pop.right != null) st.push(pop.right);
                if (pop.left != null) st.push(pop.left);
                if (cur != null) {
                    cur.left = null;
                    cur.right = new TreeNode(pop.val);
                    cur = cur.right;
                } else {
                    cur = root;
                }

            }
            preTraversal(root);
            System.out.println();
        }
    }
//leetcode submit region end(Prohibit modification and deletion)

}